package com.lottery.utils.lobbyUtils;

import com.lottery.dao.qiuqiu.accoutDao.UserDao;
import com.lottery.dao.qiuqiu.lobbyDao.BettinginfoDao;
import com.lottery.dao.qiuqiu.lobbyDao.PlaywayinfoDao;
import com.lottery.dao.qiuqiu.wealthDao.AccountDao;
import com.lottery.dao.qiuqiu.wealthDao.AccountTransactionDao;
import com.lottery.dto.BetConditionDto;
import com.lottery.dto.PlaywayDto;
import com.lottery.dto.ResultDto;
import com.lottery.entity.Account;
import com.lottery.entity.AccountTransaction;
import com.lottery.entity.Bettinginfo;
import com.lottery.entity.User;
import com.lottery.service.qiuqiu.JedisClient;
import com.lottery.service.qiuqiu.MsgService.MsgNoticeService;
import com.lottery.service.qiuqiu.lobbyService.LobbyService;
import com.lottery.utils.DateUtil;
import com.lottery.utils.DealWithDouble;
import com.lottery.utils.RandCodeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

public abstract class PlaywayUtil {
    // 每个用户每期最高下注金额
    @Value("${MAXMONEY}")
    String MAXMONEY;

    // 每个用户每期最低下注金额
    @Value("${MINMONEY}")
    String MINMONEY;

    @Resource
    protected PlaywayinfoDao playwayinfoDao;


    @Resource
    protected UserDao userDao;

    @Resource
    protected AccountDao accountDao;

    @Resource
    protected JedisClient jedis;

    @Resource
    protected BettinginfoDao bettinginfoDao;

    @Resource
    protected LobbyService lobbyService;

    @Resource
    protected AccountTransactionDao accountTransactionDao;

    @Resource
    protected MsgNoticeService msgNoticeService;


    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    //平台版本号验证
//    protected boolean judgePlatflam(Integer userId, String agencyMark) {
//        User user = userDao.selectId(userId);
//        if (agencyMark.equals(user.getAgencyId())) {
//            return true;
//        } else {
//            return false;
//        }
//    }

    protected abstract boolean judgeBetTime(); // 下注时间判断

    //每一期下注的上下线判断
    protected void judgeBetLimit(double amount, ResultDto result) {
        String max = jedis.get(MAXMONEY);
        Double maxMoney = Double.valueOf(max);
        String min = jedis.get(MINMONEY);
        double minMoney = Double.valueOf(min);
        if (amount > maxMoney || amount < minMoney) {
            result.setResultData(false, "下注金额超过限制,请阅读下注规则", 4, null);
        } else {
            result.setSuccess(true);
            result.setData(amount);
        }
    }

    //账户及账户金额的验证
    protected ResultDto judgeAccount(Integer userId, List<PlaywayDto> list, Integer lotteyType, ResultDto result) {
        Account account = accountDao.selectAccountByUserId(userId);
        if (account == null) {
            result.setData3(lotteyType);
            result.setData2(DateUtil.getFormatDate("HH:mm:ss"));
            result.setResultData(false, "该账户不存在,请联系客户查询", 2, null);
        } else {
            double amount = 0;
            for (PlaywayDto py : list) {
                amount = DealWithDouble.sum(amount, py.getBettingMoney(), 2, 4);
            }
            if (DealWithDouble.sub(account.getAccountFunds(), amount, 2, 4) < 0) {
                result.setData3(lotteyType);
                result.setData2(DateUtil.getFormatDate("HH:mm:ss"));
                result.setResultData(false, "账户余额不足", 3, null);
            } else {
                judgeBetLimit(amount, result);
            }
        }
        return result;
    }

    //先决条件判断工厂
    public ResultDto getInstance(BetConditionDto cd, int loginType) {
        int userId = cd.getUserId();
        String agencyMark = cd.getAgencyMark();
        List<PlaywayDto> list = cd.getList();
        ResultDto result = cd.getResult();
        //判断平台版本
//        if (!judgePlatflam(userId, agencyMark)) {
//            result.setData3(cd.getLotteyType());
//            result.setData2(DateUtil.getFormatDate("HH:mm:ss"));
//            result.setResultData(false, "版本不匹配,请联系客服", 5, null);
//
//        } else
        //判断下注时间
        if (!judgeBetTime()) {
            result.setData3(cd.getLotteyType());
            result.setData2(DateUtil.getFormatDate("HH:mm:ss"));
            result.setResultData(false, "还未到下注时间", 6, null);
        } else {
            //判断下注上下线
            if (loginType == 0) {
                judgeAccount(userId, list, cd.getLotteyType(), result);
            } else {
                result.setSuccess(true);
            }
        }
        return result;
    }

    //下注数据插入
    @Transactional(rollbackFor = Exception.class)
    public void insertBetData(List<PlaywayDto> list, Integer userId, int lotteyType, String agencyMark, ResultDto result) throws Exception {
        //下注表信息封装(顺带将return的数据信息保存在结果中)
        List<Bettinginfo> bettinginfos = packageBetInfo(list, userId, lotteyType, result);
        double amount = (double) result.getData();

        //获取唯一订单号
        String orderId = RandCodeUtil.getOrderId();
        for (Bettinginfo bt : bettinginfos) {
            bt.setBetOrderID(orderId);
        }

        //流水表信息封装
        AccountTransaction accountTransaction = packageWaterInfo(userId, amount, orderId);


        // 自动从余额扣除投注金额
//        Account account1 = new Account();
//        account1.setAccountFunds(amount);
//        account1.setUserId(userId);
//        accountDao.reduceAccount(account1);

        //插入数据库
        bettinginfoDao.insertBettinginfoList(bettinginfos);
        accountTransactionDao.insertAccountTransaction(accountTransaction);

        //将下注信息插入到信息通道
        insertMessage(lotteyType, userId, list,agencyMark,result);


    }

    protected abstract void insertMessage(Integer lotteyType, Integer userId, List<PlaywayDto> list, String agencyMark, ResultDto result);

    protected abstract AccountTransaction packageWaterInfo(Integer userId, double amount, String orderId);

    protected abstract List<Bettinginfo> packageBetInfo(List<PlaywayDto> list, int userId, Integer lotteyType, ResultDto result);

    public abstract void insertTourBetData(List<PlaywayDto> list, Integer userId, Integer lotteyType, String agencyMark, ResultDto result) throws Exception;
}
